package main

import (
	_ "00-LocalPackage"                       // 匿名
	Calc "04-PackageInterfaceReflection/calc" // 别名
	. "fmt"                                   // 不带前缀，不建议使用，容易重名
	"reflect"
)

import (
	hello "gitee.com/Cauchy_AQ/hello"
	helloV2 "gitee.com/Cauchy_AQ/hello/v2"
)

func function01() {
	Printf("%s\n", "不带前缀")
	Println(Calc.Add(1, 2))
}

func function02() {
	hello.SayHello()
	helloV2.SayHello("AQ")
}

// Interface
type Animal interface {
	Move()
	Say()
}

type FlyAnimal interface {
	Animal
	Fly()
}

type Dog struct{}

func (d Dog) Move() {
	Println("dog move")
}

func (d Dog) Say() {
	Println("dog say")
}

type Cat struct{}

func (c *Cat) Move() {
	Println("cat move")
}

func (c *Cat) Say() {
	Println("cat say")
}

func function03() {
	var a Animal

	var d *Dog = &Dog{}
	a = d
	a.Move() // dog move
	a.Say()  // dog say

	var c Cat = Cat{}
	a = &c
	a.Move() // cat move
	a.Say()  // cat say
}

type HomeWork interface {
	DoA()
	DoB()
}

type Week1 struct{}

func (w Week1) DoA() {}

type Week2 struct {
	Week1
}

func (w Week2) DoB() {}

type A interface {
	PlayA()
}
type B interface {
	PlayB()
}

type AB interface {
	A
	B
}

// interface{} 1
func function04() {
	a := make(map[int]interface{})
	a[1] = [...]int{1, 2, 3}
	a[2] = "Golang"
	a[3] = 123

	for k, v := range a {
		Println(k, v)
	}
	/*
		2 Golang
		3 123
		1 [1 2 3]
	*/
}

func function05() {
	var a interface{}
	a = []int{1, 2, 3}
	Println(a) // [1 2 3]

	var b any
	b = []int{0}
	Println(b) // [0]

	func(a interface{}) {
		switch a.(type) {
		case int:
			Println("int")
		case string:
			Println("string")
		default:
			Println("None")
		}
	}("123") // string
}

// 接口值
func function06() {
	var c Animal
	Println(c == nil) // true

	c = new(Cat)
	Println(c == nil) // false
	Printf("%T\n", c) // *main.Cat
}

// 类型断言
func function07() {
	var x interface{}
	x = []int{1, 2, 3}

	switch v := x.(type) {
	case int:
		Println("int", v)
	case string:
		Println("string", v)
	case []int:
		Println("[]int", v) // []int [1 2 3]
	default:
		Println("failed")
	}
}

// reflect TypeOf

func reflectType(x interface{}) {
	v := reflect.TypeOf(x)
	Printf("type:%v kind:%v\n", v.Name(), v.Kind())
}

type MyInt int

func function08() {
	var a *float32
	var b MyInt
	var c int64

	reflectType(a) // type: kind:ptr
	reflectType(b) // type:MyInt kind:int
	reflectType(c) // type:int64 kind:int64

	type ABC struct {
		name string
	}
	var d = ABC{"123"}
	reflectType(d) // type:ABC kind:struct

	e := &struct {
		ID int
	}{1010}
	reflectType(e) // type: kind:ptr
}

// reflect ValueOf

func reflectValue(x interface{}) {
	v := reflect.ValueOf(x) // reflect.Value
	k := v.Kind()
	switch k {
	case reflect.Int:
		Println("Int", v.Int())
	case reflect.Int32:
		Println("Int32", int32(v.Int()))
	case reflect.Float64:
		Println("Float64", v.Float())
	default:
		Println("None")
	}
}

func function09() {
	var a int
	var c int32 = 1
	b := 0.1
	reflectValue(a) // Int 0
	reflectValue(c) // Int32 1
	reflectValue(b) // Float64 0.1
}

// 结构体反射

type Person struct {
	Name string `info:"name"`
	Age  int8   `info:"age"`
}

func function10() {
	cauchy := &Person{
		"cauchy",
		20,
	}
	t := reflect.TypeOf(cauchy)
	v := reflect.ValueOf(cauchy)

	if t.Kind() == reflect.Ptr && v.Kind() == reflect.Ptr {
		Println("reflect.Ptr") // reflect.Ptr
	}

	for i := 0; i < t.Elem().NumField(); i++ {
		f := t.Elem().Field(i)
		Println(f.Index, f.Name, f.Type)
		Println(f.Tag.Get("info"), v.Elem().FieldByName(f.Name))
	} /*
		[0] Name string
		name cauchy
		[1] Age int8
		age 20
	*/

	value0 := v.Elem().FieldByIndex([]int{0})
	value1 := v.Elem().FieldByIndex([]int{1})
	Println(value0, value1) // cauchy 20
}

func (p *Person) SetName(name string) {
	p.Name = name
}

func (p Person) GetName() string {
	return p.Name
}

func function11() {
	p := &Person{
		"cauchy",
		20,
	}

	t := reflect.TypeOf(p)
	v := reflect.ValueOf(p)

	Println(t.Kind(), t.Elem().Kind()) // ptr struct

	// 获取的方法必须是可导出的，首字母大写
	// 指针类型获取（t.NumMethod()），所有接收者方法
	// 值类型获取（t.Elem().NumMethod()），值接收者方法
	ptrN, N := t.NumMethod(), t.Elem().NumMethod()
	Println(ptrN, N) // 2, 2

	for i := 0; i < ptrN; i++ {
		m := t.Method(i)
		Println(m.Name, m.Type, m.Func)
	} /*
		GetName func(*main.Person) string 0x1ddf80
		SetName func(*main.Person, string) 0x1ddb80
	*/

	// 通过名称获取函数
	f := v.MethodByName("GetName")
	// 如果函数存在
	if f.IsValid() && !f.IsNil() {
		ret := f.Call(nil) // 调用，不用参数 nil
		Println(ret)       // [cauchy]
	}

	// 参数必须是 []reflect.Value 类型
	v.MethodByName("SetName").Call([]reflect.Value{reflect.ValueOf("AQ")})
	ret := v.MethodByName("GetName").Call(nil)
	Println(ret) // [AQ]
}

func main() {
}
